package com.librariy.net;
import android.util.Base64;
import com.librariy.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class SSLManager {
    private final static String TAG = "SSLManager";
    private final static boolean DEBUG = false;
    private static KeyStore mTrustKeyStore=null;
    private static SSLSocketFactory mSSLSocketFactory=null;
    private static HostnameVerifier mHostnameVerifier=null;
    private static void printCertificate(Certificate... certs){
        if(certs==null) return;
        for(Certificate cert:certs){
            if (!(cert instanceof X509Certificate)) {
                continue;
            }
            Log.d(TAG, "##################################################################################");
            X509Certificate X509Cert = (X509Certificate) cert;
            Log.d(TAG, "【所有者　】：" + X509Cert.getSubjectDN() + "");
            Log.d(TAG, "【版本号　】：" + X509Cert.getVersion());
            Log.d(TAG, "【序列号　】：" + X509Cert.getSerialNumber().toString(16));
            Log.d(TAG, "【类型　　】：" + X509Cert.getType());
            Log.d(TAG, "【签发者　】：" + X509Cert.getIssuerDN());
            Log.d(TAG, "【有效期　】：" + X509Cert.getNotBefore());
            Log.d(TAG, "【签名算法】：" + X509Cert.getSigAlgName());
            Log.d(TAG, "【公钥　　】：" + X509Cert.getPublicKey());
            Log.d(TAG, "##################################################################################");
        }
    }
    protected static void println(KeyStore ks, char[] pwd) throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
        if(!DEBUG) return;
        Enumeration<String> aliases = ks.aliases();
        while (aliases.hasMoreElements()) {
            String alias = aliases.nextElement();
            printCertificate(ks.getCertificate(alias));
        }
    }
    /**
     * 载入信任证书库
     */
    protected static KeyStore buildTrustKeyStore() throws IOException, GeneralSecurityException {
        if(mTrustKeyStore==null) {
            mTrustKeyStore=KeyStore.getInstance(KeyStore.getDefaultType());
            mTrustKeyStore.load(null);
            //获取系统CA信任库
            KeyStore ca = KeyStore.getInstance("AndroidCAStore");
            ca.load(null);
            Enumeration<String> aliases = ca.aliases();
            while (aliases.hasMoreElements()) {
                String alias = aliases.nextElement();
                if (!ca.isCertificateEntry(alias)) {
                    continue;
                }
                mTrustKeyStore.setCertificateEntry(alias,ca.getCertificate(alias));
            }
            //获取本地CA信任库
            InputStream bis = SSLManager.class.getResourceAsStream("/assets/com.szry.device.trust.ca.pem");
            if (bis != null) {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                while (bis.available() > 0) {
                    Certificate cert = cf.generateCertificate(bis);
                    mTrustKeyStore.setCertificateEntry("User-Trust-Certificate-" + mTrustKeyStore.size(), cert);
                    printCertificate(cert);
                }
                bis.close();
            }else{
                Log.e(TAG, "Not found user ca[/assets/com.szry.device.trust.ca.pem]");
            }
            Log.i(TAG, "======================== TrustKeyStore(" + mTrustKeyStore.size() + ") ========================");
            println(mTrustKeyStore, null);
        }
        return mTrustKeyStore;
    }
    /**
     * 创建带信任库的SSLSocketFactory（验证服务器证书的合法性）
     */
    public static SSLSocketFactory buildSSLSocketFactory() throws Exception {
        if(mSSLSocketFactory!=null) return mSSLSocketFactory;
        // 初始化个人证书管理器
        KeyManagerFactory kmFact = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmFact.init(null, null);
        KeyManager[] kms = kmFact.getKeyManagers();
        // 初始化信任管理器
        TrustManagerFactory tmFact = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmFact.init(SSLManager.buildTrustKeyStore());
        TrustManager[] tms = tmFact.getTrustManagers();
        // 初始化SSLContext
        SSLContext sslContext = SSLContext.getInstance("SSL");        
        sslContext.init(kms, tms, null);
        mSSLSocketFactory = sslContext.getSocketFactory();
        return mSSLSocketFactory;
    }
    public static HostnameVerifier buildHostnameVerifier() throws Exception {
        if(mHostnameVerifier!=null) return mHostnameVerifier;
        mHostnameVerifier=new HostnameVerifier() {
            @Override
            public boolean verify(String host, SSLSession mSession) {
                if (host == null || mSession == null) {
                    Log.d(TAG, "[Verify]: SSL Session=" + mSession + "; Certificate.Host=" + host);
                    return false;
                } else {
                    Log.d(TAG, "[Verify]: SSL SessionID=" + Base64.encodeToString(mSession.getId(), Base64.DEFAULT) + "; Certificate.Host=" + host + "; Session.Host=" + mSession.getPeerHost());
                     return host.equals(mSession.getPeerHost());
                }
            }
        };
        return mHostnameVerifier;
    }
    //初始化
    public static void initSSL(HttpURLConnection conn) {
        try {
            if(!(conn instanceof HttpsURLConnection)) return;
            //使用证书信任库验证服务器，防止网路劫持攻击
            ((HttpsURLConnection)conn).setSSLSocketFactory(SSLManager.buildSSLSocketFactory());
            ((HttpsURLConnection)conn).setHostnameVerifier(SSLManager.buildHostnameVerifier());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
